using System;
using System.IO;
using LoggingMagic.AssemlyOperations;
using LoggingMagic.LoggingParameters;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace LoggingMagic
{
    public class LoggingTask : AppDomainIsolatedTask, ILoggingTaskAttributes
    {
        private readonly Resolver _resolver;

        [Required]
        public string Assembly { get; set; }

        [Required]
        public string References { get; set; }

        [Required]
        public string Injector { get; set; }

        public string Parameters { get; set; }

        public string KeyFile { get; set; }
        public bool RunFromExe { get; set; }


        public LoggingTask()
            : this(new Resolver())
        {
        }

        internal LoggingTask(Resolver resolver)
        {
            _resolver = resolver;
        }

        private void DoLog(string format, params object[] args)
        {
            if (!RunFromExe)
            {
                Log.LogMessage(format, args);
            }
        }

        public override bool Execute()
        {
            DoLog("Magic happens with {0}.", Assembly);
            try
            {
                var accessor = new AssemblyAccessor();
                var assemblyInfo = accessor.ParseAssembly(Assembly, References);

                var mainModule = assemblyInfo.AssemblyDefinition.MainModule;

                var factory = _resolver.CreateFactory(mainModule, assemblyInfo.AssemblyResolver, this);

                var processedLabel = factory.ProcessedLabel;
                var processor = factory.Processor;

                if (processedLabel.NeedProcessing)
                {
                    DoLog("Enchanting assembly...");
                    var result = processor.Process();

                    DoLog(result == true ? "Enchanted successfully..." : "Enchanting not needed...");

                    if (result != null)
                    {
                        if (KeyFile != null)
                            DoLog("Resigning enchanted assembly with key from {0}...", KeyFile);

                        assemblyInfo.AssemblyDefinition.Write(Assembly, accessor.MakeWriterParameters(Assembly, KeyFile));
                    }
                }
                else
                    DoLog("Assembly is already enchanted.");

                return true;
            }
            catch (FileNotFoundException)
            {
                // no files - no fun
                return false;
            }
            catch (Exception e)
            {
                Log.LogError("Unable to proceed with Logging magic {0}", e);
                DoLog(e.Message);
                return false;
            }
        }



        public string ClassName { get; set; }
        public string MethodSignature { get; set; }
        public string MethodWithParamsSignature { get; set; }
        public string LogAttributeName { get; set; }
        public string NoLogAttributeName { get; set; }
        public string LogSetters { get; set; }
        public string LogGetters { get; set; }
    }

}